/*
 * @author Ihsan Al-Hamoud
 * @Web www.al-hamoud.com
 * @Web www.patternsexpert.com
 * @version 1.0
 * If you need a completed Blogger with GWT
 * as Client side. Please email me on
 * ihsan.alhamoud@gmail.com
 * I will be very happy to help.
 */
/* implementing Bridge Pattern */

package com.patternsexpert.blog.server;

import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import com.patternsexpert.blog.client.entities.Article;

public class ArticleModel implements ArticleServices{
	
	private static final String OFFLINE		= "offline";
	private static final String ONLINE		= "online";
	private static final String AVAILABLE	= "available";
	
	private String status;
	
	private PersistenceManager pm;
	
	private String title;
	private String email;
	
	private Article copy;
	
	public ArticleModel(String title, String email){
		pm	= PMF.get().getPersistenceManager();
		
		this.title = title;
		this.email = email;
		this.status = "";
		this.copy	= null;
		
		this.initArticle();
		
	}/* End of construction */
	
	@SuppressWarnings({ "unchecked" })
	private void initArticle(){
		 String q = "title == '" + title + "' && email == '" + email + "'";
		 
		 Query query = pm.newQuery(Article.class, q);
		 
		 try{
			List<Article> results =
			 (List<Article>) query.execute();
			
			if(results.isEmpty()){
				/* You can call method create */
				this.status = AVAILABLE;
				
			}/* End of if for creating
			  * a new Article for the first time
			  */
			else{
				for(Article current: results){
					
					if(current.isPublished().equalsIgnoreCase("n")){
						this.status = OFFLINE;
						
						/* do a copy of the current article 
						 * to the copy article to do update
						 * at the updateArticle function
						 */
						this.copy = pm.detachCopy(current);
					}/* End of if for non publish article */
					else{
						this.status = ONLINE;
						
					}/* End of else for publishing articles */
					
				}// End of loop for fetching article result 
				
			}/* End of else for existing Article */
			
		 }/* End of try for getting the articles as List*/
		 catch(Throwable e){
			 System.out.println(e.getMessage());
		 }// end of catch Error
		 finally{
			 query.closeAll();
			 pm.close();
		 }/* End of finally for closing Query */
	}/* End of initArticle */

	@Override
	public Article checkArticle(){
		/*
		 * The status must be create 
		 * at initiation class to 
		 * conduct this function
		 * AND at the end of 
		 * if stmt. MUST method
		 * return null 
		 * 
		 * OTHERWISE load an OFFLINE article  
		 */
		if(this.status.equalsIgnoreCase(AVAILABLE)){
			
			Article c = new Article();
			
			PersistenceManager upm = null;
			Transaction txn = null;
			
			/* insert into DB */
			try{
				upm = PMF.get().getPersistenceManager();
				txn = upm.currentTransaction();
				txn.begin();
				
				c.setTitle(title);
				c.setEmail(email);
				c.setPublished("n");
				c.setSpam("n");
				
				c.setCategory("");
				c.setDate(new Date());
				c.setDescriptoin("");
				c.setText("");
				
				upm.makePersistent(c);
				txn.commit();
				
				//pm.makePersistent(c);
			}/* End of try for trying to updating in DB*/
			catch(Throwable e){
						
				System.out.println(e.getMessage());
			}// end of catch			/* end of inserting into DB */
			
			/* Return null means, a new article has been created */
			return null;
			
		}/* End of if for verification the creation */
		else{
			/* This means an OFFLINE status 
			 * MUST be as true 
			 */
			if(this.status.equalsIgnoreCase(OFFLINE)){
				return this.copy;
			}/* End of if stmt. for confirmation
			  * OFFLINE status 
			  */
			
			else{
				return null;
			}// end of else @ status should be ONLNE 
			
		}/* End of else for non creation the article */
		
	}/* End of createArticle for the first time*/

	@Override
	public void updateArticle(String cat, 
							  String des,
							  String text){
		/*
		 * The status must be update 
		 * at initiate class to 
		 * conduct this function
		 */
		if (status.equalsIgnoreCase(OFFLINE)){
			
			if(this.copy != null){
		///////////////// STEPS TO UPDATE DB //////////////////////
			
				PersistenceManager upm = null;
				Transaction txn = null;
				
				try{
					upm = PMF.get().getPersistenceManager();
					txn = upm.currentTransaction();
					txn.begin();
					
					this.copy.setCategory(cat);
					this.copy.setDate(new Date());
					this.copy.setDescriptoin(des);
					this.copy.setPublished("n");
					this.copy.setSpam("n");
					this.copy.setText(text);
				
					upm.makePersistent(this.copy);
					txn.commit();

				}catch (Throwable e){
					upm.currentTransaction().rollback();
					
				}finally{
					upm.close();
				} /* end of finally to close the DB connection */
				
		//////////////// END OF UPDATING DB //////////////

				
			}/* End of if for updating the article */
			
		}/* End of if for verification the update */
		
	}/* End of updateArticle for the non published article */
	
	@Override
	public void publishArticle() {
		/*
		 * The status must be update 
		 * at initiate class to 
		 * conduct this function
		 */
		if (status.equalsIgnoreCase(OFFLINE)){
			if(this.copy != null){
		///////////////// STEPS TO UPDATE DB //////////////////////
				PersistenceManager upm = null;
				Transaction txn = null;
				
				try{
					upm = PMF.get().getPersistenceManager();
					txn = upm.currentTransaction();
					txn.begin();
					
					this.copy.setPublished("y");
				
					upm.makePersistent(this.copy);
					txn.commit();

				}catch (Throwable e){
					upm.currentTransaction().rollback();
					
				}finally{
					upm.close();
				} /* end of finally to close the DB connection */

		//////////////// END OF UPDATING DB ////////////////////////
				
		 }// end of if that copy is not null
			
	  }// end of if that the status is OFFLINE
		
	}/* End of publishArticle */
	
	@Override
	public List<Article> retrieveArticles() {
		return null;	
	}/* End of retrieveArticles */

	@Override
	public void deleteArticle(){	
		
	}/* End of deleteArticle */

	@Override
	public void setArticleAsSpam() {
		
	}/* End of setArticleAsSpam */
	
	@Override
	public Article retrieveArticle() {
		return this.copy != null ? this.copy: null;
	}/* End of retrieveArticle */
	
}/* End of class ArticleModel */